/*============================================================================*/
/*  Copyright (C) 2009-2011,  INFRASTRUCTURE SOFTWARE CO.,LTD.
 *  
 *  All rights reserved. This software is  property. Duplication 
 *  or disclosure without  written authorization is prohibited.
 *  
 *  
 *  @file       CanTp_RX.c
 *  @brief      <Briefly describe file(one line)>
 *  
 *  <Compiler: CANTP    MCU:CANTP>
 *  
 *  @author     stanley
 *  @date       2013-4-7
 */
/*============================================================================*/


/*=======[R E V I S I O N   H I S T O R Y]====================================*/
/*  <VERSION>    <DATE>    <AUTHOR>    <REVISION LOG>
 *  V1.0.0       
 *  V1.0.1       2019-12-5 tao.yu     QAC change
 *  V1.0.2       2020-1-7  tao.yu     Commercial project problem modification
 * 
 *  
 */
/*============================================================================*/

/*=======[V E R S I O N  I N F O R M A T I O N]===============================*/
#define CANTP_RX_C_AR_MAJOR_VERSION  4
#define CANTP_RX_C_AR_MINOR_VERSION  2
#define CANTP_RX_C_AR_PATCH_VERSION  2
#define CANTP_RX_C_SW_MAJOR_VERSION  1
#define CANTP_RX_C_SW_MINOR_VERSION  0
#define CANTP_RX_C_SW_PATCH_VERSION  2

/*required CANIF version*/
#define CANTP_RX_C_CANIF_AR_MAJOR_VERSION  4
#define CANTP_RX_C_CANIF_AR_MINOR_VERSION  2

/*required PDUR version*/
#define CANTP_RX_C_PDUR_AR_MAJOR_VERSION  4
#define CANTP_RX_C_PDUR_AR_MINOR_VERSION  2

/*required DEM version*/
#define CANTP_RX_C_DEM_AR_MAJOR_VERSION  4
#define CANTP_RX_C_DEM_AR_MINOR_VERSION  2

/*required DET version*/
#define CANTP_RX_C_DET_AR_MAJOR_VERSION  4
#define CANTP_RX_C_DET_AR_MINOR_VERSION  2

/*=======[I N C L U D E S]====================================================*/
#include "CanTp.h"
#include "CanTp_Internal.h"

/*=======[V E R S I O N  C H E C K]===========================================*/
/*Check version information with CanTp.h*/
#if (CANTP_RX_C_AR_MAJOR_VERSION != CANTP_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with CanTp.h"
#endif
#if (CANTP_RX_C_AR_MINOR_VERSION != CANTP_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with CanTp.h"
#endif
#if (CANTP_RX_C_AR_PATCH_VERSION != CANTP_H_AR_PATCH_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Patch Version with CanTp.h"
#endif
#if (CANTP_RX_C_SW_MAJOR_VERSION != CANTP_H_SW_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Major Version with CanTp.h"
#endif
#if (CANTP_RX_C_SW_MINOR_VERSION != CANTP_H_SW_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Minor Version with CanTp.h"
#endif

/*Check version information with CanTp_Internal.h*/
#if (CANTP_RX_C_AR_MAJOR_VERSION != CANTP_INTERNAL_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with CanTp_Internal.h"
#endif
#if (CANTP_RX_C_AR_MINOR_VERSION != CANTP_INTERNAL_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with CanTp_Internal.h"
#endif
#if (CANTP_RX_C_AR_PATCH_VERSION != CANTP_INTERNAL_H_AR_PATCH_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Patch Version with CanTp_Internal.h"
#endif
#if (CANTP_RX_C_SW_MAJOR_VERSION != CANTP_INTERNAL_H_SW_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Major Version with CanTp_Internal.h"
#endif
#if (CANTP_RX_C_SW_MINOR_VERSION != CANTP_INTERNAL_H_SW_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Minor Version with CanTp_Internal.h"
#endif

/*check version information with CanTp_Types.h*/
#if (CANTP_RX_C_AR_MAJOR_VERSION != CANTP_TYPES_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with CanTp_Types.h"
#endif
#if (CANTP_RX_C_AR_MINOR_VERSION != CANTP_TYPES_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with CanTp_Types.h"
#endif
#if (CANTP_RX_C_AR_PATCH_VERSION != CANTP_TYPES_H_AR_PATCH_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Patch Version with CanTp_Types.h"
#endif
#if (CANTP_RX_C_SW_MAJOR_VERSION != CANTP_TYPES_H_SW_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Major Version with CanTp_Types.h"
#endif
#if (CANTP_RX_C_SW_MINOR_VERSION != CANTP_TYPES_H_SW_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Minor Version with CanTp_Types.h"
#endif

/*check version information with CanTp_Cfg.h*/
#if (CANTP_RX_C_AR_MAJOR_VERSION != CANTP_CFG_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with CanTp_Cfg.h"
#endif
#if (CANTP_RX_C_AR_MINOR_VERSION != CANTP_CFG_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with CanTp_Cfg.h"
#endif
#if (CANTP_RX_C_AR_PATCH_VERSION != CANTP_CFG_H_AR_PATCH_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Patch Version with CanTp_Cfg.h"
#endif
#if (CANTP_RX_C_SW_MAJOR_VERSION != CANTP_CFG_H_SW_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Major Version with CanTp_Cfg.h"
#endif
#if (CANTP_RX_C_SW_MINOR_VERSION != CANTP_CFG_H_SW_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Software Implementation Minor Version with CanTp_Cfg.h"
#endif

/*check version information with DEM*/
#if (CANTP_RX_C_DEM_AR_MAJOR_VERSION != DEM_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with Dem.h"
#endif
#if (CANTP_RX_C_DEM_AR_MINOR_VERSION != DEM_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with Dem.h"
#endif

#if (CANTP_DEV_ERROR_DETECT == STD_ON)
/*Check version information with DET*/
#if (CANTP_RX_C_DET_AR_MAJOR_VERSION != DET_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with Det.h"
#endif
#if (CANTP_RX_C_DET_AR_MINOR_VERSION != DET_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with Det.h"
#endif
#endif

/*Check version information with PDUR*/
#if (CANTP_RX_C_PDUR_AR_MAJOR_VERSION != PDUR_CANTP_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with PduR_CanTp.h"
#endif
#if (CANTP_RX_C_PDUR_AR_MINOR_VERSION != PDUR_CANTP_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with PduR_CanTp.h"
#endif

/*Check version information with CANIF*/
#if (CANTP_RX_C_CANIF_AR_MAJOR_VERSION != CANIF_H_AR_MAJOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Major Version with CanIf.h"
#endif
#if (CANTP_RX_C_CANIF_AR_MINOR_VERSION != CANIF_H_AR_MINOR_VERSION)
  #error "CanTp_RX.c : Mismatch in Specification Minor Version with CanIf.h"
#endif
/*=======[M A C R O S]========================================================*/

/*=======[T Y P E   D E F I N I T I O N S]====================================*/

/*=======[E X T E R N A L   D A T A]==========================================*/

/*=======[E X T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/

/*=======[I N T E R N A L   D A T A]==========================================*/

/*=======[I N T E R N A L   F U N C T I O N   D E C L A R A T I O N S]========*/
#define CANTP_START_SEC_CODE
#include "Cantp_MemMap.h"
/*************************************************************************/
/*
 * Brief               Construct Flow Control frame according to the parameter.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 *                     FsValue FC FS value
 *                     BSValue BS value for FC
 *                     STminValue STMin for FC
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              the length of constructed FC
 * PreCondition        Module initialized, a FC transmitting needed.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
static FUNC(PduLengthType, CANTP_CODE)
CanTp_ConstructFCPci(
    uint8 ChannelIdx,
    uint8 FsValue,
    uint8 BSValue,
    uint8 STminValue);

#if (CANTP_GENERIC_CONNECTION_SUPPORT == STD_ON)
static FUNC(void, CANTP_CODE)CanTp_ConstructForwardRxMetaData(
	uint8 channelId,
	P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
	P2VAR(PduInfoType, AUTOMATIC, CANTP_VAR) CanTpRxInfoPtr);
#endif

static FUNC(Std_ReturnType, CANTP_CODE)
CanTp_CompareBufferWithBs(uint8 ChannelIdx);

/*************************************************************************/
/*
 * Brief               Calculate the BS value according to the buffer length and remain data length.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, a FC transmitting needed to start a new block.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
static FUNC(void, CANTP_CODE)
CanTp_CalcBS(uint8 ChannelIdx);

/*************************************************************************/
/*
 * Brief               Start a block by sending FC_CTS if needed.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, need to start a new block.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
static FUNC(Std_ReturnType, CANTP_CODE)
CanTp_RxBlockStart(uint8 ChannelIdx);

/*=======[F U N C T I O N   I M P L E M E N T A T I O N S]====================*/
/*************************************************************************/
/*
 * Brief               Get RX-SDU configuration by received NPDU information.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      CanTpRxPduId ID of the received NPDU
 *                     CanTpRxPduPtr pointer to the received NPDU data
 *                     SduFrameType pointer to store the frame type
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              pointer to the configuration structure of this SDU
 *                     NULL_PTR if the no SDU matched
 * PreCondition        Module initialized
 * CallByAPI           CanTp Internal
 */
/*************************************************************************/
FUNC(P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST), CANTP_CODE)
CanTp_GetRxSduCfgByNpdu(
    PduIdType CanTpRxPduId,
    P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr,
    P2VAR(CanTp_FramePCIType, AUTOMATIC, AUTOMATIC) SduFrameType,
	P2VAR(uint8, AUTOMATIC, AUTOMATIC) channelIdx
    )
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) result = NULL_PTR;
    P2CONST(CanTp_ChannelType, AUTOMATIC, CANTP_VAR) channelPtr;
    uint8 rxNSduIdx;
    uint8 chnIdx;
    CanTp_FramePCIType frameType;

    for (chnIdx = 0; (NULL_PTR == result) && (chnIdx < CANTP_CHANNEL_NUMBER); chnIdx++)
    {
    	channelPtr = &CanTp_CfgData.CanTpChannel[chnIdx];
		for (rxNSduIdx = 0; (NULL_PTR == result) && (rxNSduIdx < channelPtr->RxNSduNum); rxNSduIdx++)
		{
			switch (channelPtr->RxNSdus[rxNSduIdx].AddressingFormat)
			{
				case CANTP_STANDARD:
				{
					frameType = CanTpRxPduPtr->SduDataPtr[CANTP_PCI_OFFSET_STD] & CANTP_FTYPE_MASK;
					if ((channelPtr->RxNSdus[rxNSduIdx].RxNPduId == CanTpRxPduId)
						&& ((CANTP_FTYPE_CF == frameType)||(CANTP_FTYPE_SF == frameType)||(CANTP_FTYPE_FF == frameType)))
					{
						result = &channelPtr->RxNSdus[rxNSduIdx];
						*SduFrameType = frameType;
						*channelIdx = chnIdx;
					}
					break;
				}
				#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
				case CANTP_EXTENDED:
				{
					if (CanTpRxPduPtr->SduLength > CANTP_PCI_OFFSET_EX)
					{
						/*check this RX-SDU, which is configured as extended addressing format, and the CAN data at least includes
						 TA and PCIType*/
						/*check its TA and frame type*/
						frameType  = CanTpRxPduPtr->SduDataPtr[CANTP_PCI_OFFSET_EX] & CANTP_FTYPE_MASK;

						if ((channelPtr->RxNSdus[rxNSduIdx].RxNPduId == CanTpRxPduId)
							&& ((CANTP_FTYPE_CF == frameType)||(CANTP_FTYPE_SF == frameType)||(CANTP_FTYPE_FF == frameType)))
						{
							result = &channelPtr->RxNSdus[rxNSduIdx];
							*SduFrameType = frameType;
							*channelIdx = chnIdx;
						}
					}
					else
					{
						/*configured as extended addressing format, but the received NPDU not has enough data space*/
					}
					break;
				}
				#endif/*ENDOF extended addressing mode*/
				#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
				case CANTP_NORMALFIXED:
				{
					frameType = CanTpRxPduPtr->SduDataPtr[CANTP_PCI_OFFSET_NF] & CANTP_FTYPE_MASK;
					if ((channelPtr->RxNSdus[rxNSduIdx].RxNPduId == CanTpRxPduId)
						&& ((CANTP_FTYPE_CF == frameType)||(CANTP_FTYPE_SF == frameType)||(CANTP_FTYPE_FF == frameType)))
					{
						result = &channelPtr->RxNSdus[rxNSduIdx];
						*SduFrameType = frameType;
						*channelIdx = chnIdx;
					}
					break;
				}
				#endif/*ENDOF normal fixed addressing mode*/
				#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
				case CANTP_MIXED:
				{
					if (CanTpRxPduPtr->SduLength > CANTP_PCI_OFFSET_MIX11)
					{
						/*check this RX-SDU, which is configured as mix11 addressing format, and the CAN data at least includes
						 AE and PCIType*/
						/*check its TA and frame type*/
						frameType  = CanTpRxPduPtr->SduDataPtr[CANTP_PCI_OFFSET_MIX11] & CANTP_FTYPE_MASK;

						if ((channelPtr->RxNSdus[rxNSduIdx].RxNPduId == CanTpRxPduId)
							&& ((CANTP_FTYPE_CF == frameType)||(CANTP_FTYPE_SF == frameType)||(CANTP_FTYPE_FF == frameType)))
						{
							result = &channelPtr->RxNSdus[rxNSduIdx];
							*SduFrameType = frameType;
							*channelIdx = chnIdx;
						}
					}
					else
					{
						/*configured as mix11 addressing format, but the received NPDU not has enough data space*/
					}
					break;
				}
				#endif/*ENDOF mix11 addressing mode*/
				#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
				case CANTP_MIXED29BIT:
				{
					if (CanTpRxPduPtr->SduLength > CANTP_PCI_OFFSET_MIX29)
					{
						/*check this RX-SDU, which is configured as mix29 addressing format, and the CAN data at least includes
						 AE and PCIType*/
						/*check its TA and frame type*/
						frameType  = CanTpRxPduPtr->SduDataPtr[CANTP_PCI_OFFSET_MIX29] & CANTP_FTYPE_MASK;

						if ((channelPtr->RxNSdus[rxNSduIdx].RxNPduId == CanTpRxPduId)
							&& ((CANTP_FTYPE_CF == frameType)||(CANTP_FTYPE_SF == frameType)||(CANTP_FTYPE_FF == frameType)))
						{
							result = &channelPtr->RxNSdus[rxNSduIdx];
							*SduFrameType = frameType;
							*channelIdx = chnIdx;
						}
					}
					else
					{
						/*configured as mix29 addressing format, but the received NPDU not has enough data space*/
					}
					break;
				}
				#endif/*ENDOF mix29 addressing mode*/
				default:
					break;
			}/*END OF switch*/
       } /*END OF for loop*/
    } /*END OF for loop*/
    return result;
}

/*************************************************************************/
/*
 * Brief               Get Rx-SDU configuration by Tx-FC NPDUID.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      CanTpTxPduId ID of the NPDU ID of TX FC
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              pointer to the configuration structure of this SDU
 *                     NULL_PTR if the no SDU matched
 * PreCondition        Module initialized
 * CallByAPI           CanTp Internal
 */
/*************************************************************************/
FUNC(P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST), CANTP_CODE)
CanTp_GetRxSduCfgByTxFCNPdu(PduIdType CanTpTxPduId, uint8 *channelId)
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) result = NULL_PTR;
    P2CONST(CanTp_ChannelType, AUTOMATIC, CANTP_VAR) channelPtr;
    uint8 rxNSduIdx;
    uint8 chnIdx;

    for (chnIdx = 0; (NULL_PTR == result) && (chnIdx < CANTP_CHANNEL_NUMBER); chnIdx++)
    {
    	channelPtr = &CanTp_CfgData.CanTpChannel[chnIdx];
		for (rxNSduIdx = 0; (NULL_PTR == result) && (rxNSduIdx < channelPtr->RxNSduNum); rxNSduIdx++)
		{
			if ((channelPtr->RxNSdus[rxNSduIdx].TxFcNPduId == CanTpTxPduId)
				&&((CANTP_PHYSICAL_RX == channelPtr->RxNSdus[rxNSduIdx].RxTaType)
					#if (STD_ON == CANTP_FD)
					||(CANTP_CANFD_PHYSICAL == channelPtr->RxNSdus[rxNSduIdx].RxTaType)
					#endif
					))
			{
				result = &channelPtr->RxNSdus[rxNSduIdx];
				*channelId = chnIdx;
			}
		}
    }
    return result;
}
/*************************************************************************/
/*
 * Brief               Handle received CF.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx channel index
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, the channel is waiting for CF,
 *                     and CF received
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
FUNC(void, CANTP_CODE)
CanTp_RxHandleCFReception(uint8 ChannelIdx)
{
    uint8 cfSN = 0;
    uint8 chnIdx;
    PduIdType nSduId;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxNSduCfgPtr;
	boolean finished = FALSE;
	PduInfoType pduInfo;
	P2VAR(PduInfoType, AUTOMATIC, AUTOMATIC) pduInfoPtr = &pduInfo;
	PduIdType iPduId;
	uint32 N_Cr;
	PduLengthType position;
	Std_ReturnType rslt;
	BufReq_ReturnType bufRslt;

    nSduId = CanTp_Channels[ChannelIdx].RxConnection.NSduId;
    rxNSduCfgPtr = CanTp_GetRxSduCfgByNSduId(nSduId, &chnIdx);
    iPduId = rxNSduCfgPtr->RxIPduId;

    if (CANTP_STANDARD == rxNSduCfgPtr->AddressingFormat)
    {
        /*standard SDU*/
		cfSN = CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[CANTP_PCI_OFFSET_STD] & CANTP_CF_SN_MASK;
		/*update local buffer information*/
		CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_CF_DATA_OFFSET_STD;
    }
	#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_EXTENDED == rxNSduCfgPtr->AddressingFormat)
    {
        /*extended SDU*/
        cfSN = CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[CANTP_PCI_OFFSET_EX] & CANTP_CF_SN_MASK;
        /*update local buffer information*/
        CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_CF_DATA_OFFSET_EX;
    }
	#endif
	#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_NORMALFIXED == rxNSduCfgPtr->AddressingFormat)
	{
		/*extended SDU*/
		cfSN = CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[CANTP_PCI_OFFSET_NF] & CANTP_CF_SN_MASK;
		/*update local buffer information*/
		CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_CF_DATA_OFFSET_NF;
	}
	#endif
	#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED == rxNSduCfgPtr->AddressingFormat)
	{
		/*extended SDU*/
		cfSN = CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[CANTP_PCI_OFFSET_MIX11] & CANTP_CF_SN_MASK;
		/*update local buffer information*/
		CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_CF_DATA_OFFSET_MIX11;
	}
	#endif
	#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED29BIT == rxNSduCfgPtr->AddressingFormat)
	{
		/*extended SDU*/
		cfSN = CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[CANTP_PCI_OFFSET_MIX29] & CANTP_CF_SN_MASK;
		/*update local buffer information*/
		CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_CF_DATA_OFFSET_MIX29;
	}
	else
	{
	    /*idle*/
	}
	#endif
	CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen = CanTp_Channels[ChannelIdx].RxConnection.DataLen -
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition - rxNSduCfgPtr->MetaDataLength;

    /*check SN value*/
    if (cfSN != CanTp_Channels[ChannelIdx].RxConnection.CurrentCfSn)
    {
        /*wrong SN*/
        /*release resource of channel*/
    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
    	{
    		CanTp_InitChannel(ChannelIdx);
    	}
    	else
    	{
    		CanTp_InitRxChannel(ChannelIdx);
    	}
        PduR_CanTpRxIndication(iPduId, E_NOT_OK);
    }
    else
    {
        /*It is the expected CF*/
        CanTp_Channels[ChannelIdx].RxConnection.HandleType = CANTP_FTYPE_CF;
        CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_TIMER_NONE;
        if (0xFFu > CanTp_Channels[ChannelIdx].RxConnection.HandledCfCount)
        {
            CanTp_Channels[ChannelIdx].RxConnection.HandledCfCount++;
        }

        /*consider rx padding*/
        if (CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen > CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining)
        {
            CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen = CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining;
        }

        position = CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition;
        pduInfo.SduDataPtr = &(CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[position]);
        pduInfo.SduLength = CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen;
        bufRslt = PduR_CanTpCopyRxData(iPduId, pduInfoPtr, &CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining);
        /*SWS_CanTp_00271*/
        if (BUFREQ_E_NOT_OK == bufRslt)
        {
        	/*release resource of channel*/
        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
        	{
        		CanTp_InitChannel(ChannelIdx);
        	}
        	else
        	{
        		CanTp_InitRxChannel(ChannelIdx);
        	}
			PduR_CanTpRxIndication(iPduId, E_NOT_OK);
        }
        else
        {
        	CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining =
					CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining -
					CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen;

	        if ((CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen < 7u)
	        		&& (0u != CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining))
	        {
	        	/*release resource of channel*/
	        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
	        	{
	        		CanTp_InitChannel(ChannelIdx);
	        	}
	        	else
	        	{
	        		CanTp_InitRxChannel(ChannelIdx);
	        	}
				PduR_CanTpRxIndication(iPduId, E_NOT_OK);
	        }
			if (0u == CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining)
			{
				/*the whole SDU reception finished*/
				/*release resource of channel*/
		    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
		    	{
		    		CanTp_InitChannel(ChannelIdx);
		    	}
		    	else
		    	{
		    		CanTp_InitRxChannel(ChannelIdx);
		    	}
				PduR_CanTpRxIndication(iPduId, E_OK);
				finished = TRUE;
			}
			else /*SDU whole reception not finished*/
			{
				if (CanTp_Channels[ChannelIdx].RxConnection.CurrentBs == CanTp_Channels[ChannelIdx].RxConnection.HandledCfCount)
				{
					/*current block finished, check upper buffer is enough or not*/
					rslt = CanTp_CompareBufferWithBs(ChannelIdx);
					if (E_NOT_OK == rslt)
					{
						/*the upper buffer is not enough to store the next block, so need to get more buffer*/
						CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_START;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NB;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = rxNSduCfgPtr->Nbr;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
					}
					else
					{
						/*buffer enough, start a new block*/
						rslt = CanTp_RxBlockStart(ChannelIdx);
						if (E_NOT_OK == rslt)
						{
					    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
					    	{
					    		CanTp_InitChannel(ChannelIdx);
					    	}
					    	else
					    	{
					    		CanTp_InitRxChannel(ChannelIdx);
					    	}
							PduR_CanTpRxIndication(iPduId, E_NOT_OK);
						}
					}
				}
				else
				{
					/*continue to wait another CF*/
					CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_V4CF;
				    if (rxNSduCfgPtr->Ncr != NULL_PTR)
				    {
				    	N_Cr = *(rxNSduCfgPtr->Ncr);
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NC;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = N_Cr;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
				    }
				    else
				    {
				    	CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_TIMER_NONE;
				    }
				}
				/*update SN,expect next CF*/
				CanTp_Channels[ChannelIdx].RxConnection.CurrentCfSn =
						(uint8)(CanTp_Channels[ChannelIdx].RxConnection.CurrentCfSn + 1u) & CANTP_CF_SN_MASK;

			} /*END OF SDU whole reception not finished*/
        } /*END OF if (BUFREQ_E_NOT_OK == bufRslt)*/
    } /*END OF handling expected CF*/

    /*clear the event*/
	if (FALSE == finished)
	{
        CanTp_Channels[ChannelIdx].RxConnection.EventFlags =
        		CanTp_Channels[ChannelIdx].RxConnection.EventFlags & ((uint8)~CANTP_CHANNEL_EVENT_CF_RECEIVED);
    }
}

/*FF come, just execute one time of PduR_CanTpStartOfReception*/
FUNC(void, CANTP_CODE)
CanTp_RxHandleFFStart(uint8 ChannelIdx)
{
	PduIdType iPduId;
    PduIdType nSduId;
	PduInfoType pduInfo;
	P2VAR(PduInfoType, AUTOMATIC, AUTOMATIC) pduInfoPtr = &pduInfo;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    BufReq_ReturnType bufRslt;
    Std_ReturnType rslt;
    PduLengthType position;
    uint8 chnIdx;

    pduInfo.SduLength = 0;
    nSduId = CanTp_Channels[ChannelIdx].RxConnection.NSduId;
    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(nSduId, &chnIdx);
    iPduId = rxSduCfgPtr->RxIPduId;
	#if (CANTP_GENERIC_CONNECTION_SUPPORT == STD_ON)
    if (CanTp_Channels[ChannelIdx].RxConnection.MetaDataLength > 0u)
    {
    	CanTp_ConstructForwardRxMetaData(ChannelIdx, rxSduCfgPtr, pduInfoPtr);
    }
	#endif

    bufRslt = PduR_CanTpStartOfReception(
    		iPduId,
			pduInfoPtr,
			CanTp_Channels[ChannelIdx].RxConnection.SduDataTotalCount,
			&CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining);

	switch (bufRslt)
	{
		case BUFREQ_OK:
		{
			if (CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen > CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining)
			{
				/*SWS_CanTp_00339*/
		    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
		    	{
		    		CanTp_InitChannel(ChannelIdx);
		    	}
		    	else
		    	{
		    		CanTp_InitRxChannel(ChannelIdx);
		    	}
				PduR_CanTpRxIndication(iPduId, E_NOT_OK);
			}
			else
			{
				position = CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition;
				pduInfo.SduDataPtr = &CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[position];
				pduInfo.SduLength = CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen;
				bufRslt = PduR_CanTpCopyRxData(iPduId, pduInfoPtr, &CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining);
				if (BUFREQ_E_NOT_OK == bufRslt)
				{
			    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
			    	{
			    		CanTp_InitChannel(ChannelIdx);
			    	}
			    	else
			    	{
			    		CanTp_InitRxChannel(ChannelIdx);
			    	}
					PduR_CanTpRxIndication(iPduId, E_NOT_OK);
				}
				else
				{
					CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining =
							CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining - CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen;
					/*calculate block size*/
					CanTp_CalcBS(ChannelIdx);
					/*SWS_CanTp_00082,check upper layer buffer is enough or not for next block*/
					rslt = CanTp_CompareBufferWithBs(ChannelIdx);
					if (E_NOT_OK == rslt)
					{
						/*the upper buffer is not enough to store the next block, so need to get more buffer*/
						CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_START;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NB;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = rxSduCfgPtr->Nbr;
						CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
					}
					else
					{
						/*buffer enough, start a new block*/
						rslt = CanTp_RxBlockStart(ChannelIdx);
						if (E_NOT_OK == rslt)
						{
					    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
					    	{
					    		CanTp_InitChannel(ChannelIdx);
					    	}
					    	else
					    	{
					    		CanTp_InitRxChannel(ChannelIdx);
					    	}
							PduR_CanTpRxIndication(iPduId, E_NOT_OK);
						}
					}
				}
	    		/*update expected next SN*/
				CanTp_Channels[ChannelIdx].RxConnection.CurrentCfSn =
						(uint8)(CanTp_Channels[ChannelIdx].RxConnection.CurrentCfSn + 1u) & CANTP_CF_SN_MASK;
			}
			break;
		}
		case BUFREQ_E_NOT_OK:
		{
			/*SWS_CanTp_00081*/
	    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
	    	{
	    		CanTp_InitChannel(ChannelIdx);
	    	}
	    	else
	    	{
	    		CanTp_InitRxChannel(ChannelIdx);
	    	}
			break;
		}
		case BUFREQ_E_OVFL:
		{
			/*the CanTp module shall send a Flow Control N-PDU with overflow status (FC(OVFLW)) and abort the N-SDU reception*/
			/*SWS_CanTp_00318,when handling FF, send FC_OVFL*/
			pduInfo.SduLength = CanTp_ConstructFCPci(ChannelIdx, CANTP_FC_FS_OVFLW, 0, 0);
			pduInfo.SduDataPtr = CanTp_Channels[ChannelIdx].RxConnection.FcBuf;
			(void)CanIf_Transmit(rxSduCfgPtr->TxFcLPduId, pduInfoPtr);

			/*release resource of the channel*/
	    	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
	    	{
	    		CanTp_InitChannel(ChannelIdx);
	    	}
	    	else
	    	{
	    		CanTp_InitRxChannel(ChannelIdx);
	    	}
			break;
		}
		default:
			break;
	}
}
/*************************************************************************/
/*
 * Brief               Handle received FF.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx channel index
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, the channel is allowed to receive FF,
 *                     and FF received
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
FUNC(void, CANTP_CODE)
CanTp_RxHandleFFReception(uint8 ChannelIdx)
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxNSduCfgPtr;
    PduLengthType ffDl;

    rxNSduCfgPtr = CanTp_GetRxSduCfgByNSduId(CanTp_Channels[ChannelIdx].RxConnection.RcvdNSduId, &ChannelIdx);

    if ((CANTP_SF_RECEIVING == CanTp_Channels[ChannelIdx].RxConnection.RootState)
        || (CANTP_LARGE_RECEIVING == CanTp_Channels[ChannelIdx].RxConnection.RootState))
    {
        /*Another SF received when the channel is receiving a SDU*/
        /*Notify error for old SDU reception*/
        PduR_CanTpRxIndication(rxNSduCfgPtr->RxIPduId, E_NOT_OK);
    }

    ffDl = CanTp_RxGetFFDl(CanTp_Channels[ChannelIdx].RxConnection.LocalBuf, rxNSduCfgPtr);
    if (0u == ffDl)
    {
        PduR_CanTpRxIndication(rxNSduCfgPtr->RxIPduId, E_NOT_OK);
    }

    /*update channel runtime information*/
    CanTp_Channels[ChannelIdx].RxConnection.RootState = CANTP_LARGE_RECEIVING;
    CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_FF_START;
    CanTp_Channels[ChannelIdx].RxConnection.NSduId = CanTp_Channels[ChannelIdx].RxConnection.RcvdNSduId;
    /*SWS_CanTp_00166,the CanTp module shall start a time-out N_Br before calling PduR_CanTpStartOfReception*/
    CanTp_Channels[ChannelIdx].RxConnection.RcvdNSduId = 0;
    CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NB;
    CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = rxNSduCfgPtr->Nbr;
    CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
    CanTp_Channels[ChannelIdx].RxConnection.HandleType = CANTP_FTYPE_FF;

    if (CANTP_STANDARD == rxNSduCfgPtr->AddressingFormat)
    {
    	/*standard FF*/
    	if (ffDl <= CANTP_FF_DL_12bit_LENGTH)
    	{
    		/*FF_DL less than or equal to 4095*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_LT4095_STD;
    	}
    	else
    	{
    		/*FF_DL bigger than 4095*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_BT4095_STD;
    	}
    }
	#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_EXTENDED == rxNSduCfgPtr->AddressingFormat)
    {
        /*extended FF*/
    	if (ffDl <= CANTP_FF_DL_12bit_LENGTH)
		{
			/*FF_DL less than or equal to 4095*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_LT4095_EX;
		}
		else
		{
			/*FF_DL bigger than 4095*/
			/*update local information*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_BT4095_EX;
		}
    }
	#endif
	#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_NORMALFIXED == rxNSduCfgPtr->AddressingFormat)
	{
		if (ffDl <= CANTP_FF_DL_12bit_LENGTH)
		{
			/*FF_DL less than or equal to 4095*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_LT4095_NF;
		}
		else
		{
			/*FF_DL bigger than 4095*/
			/*update local information*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_BT4095_NF;
		}
	}
	#endif
	#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED == rxNSduCfgPtr->AddressingFormat)
	{
		if (ffDl <= CANTP_FF_DL_12bit_LENGTH)
		{
			/*FF_DL less than or equal to 4095*/
			/*update local information*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_LT4095_MIX11;
		}
		else
		{
			/*FF_DL bigger than 4095*/
			/*update local information*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_BT4095_MIX11;
		}
	}
	#endif
	#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED29BIT == rxNSduCfgPtr->AddressingFormat)
	{
		if (ffDl <= CANTP_FF_DL_12bit_LENGTH)
		{
			/*FF_DL less than or equal to 4095*/
			/*update local information*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_LT4095_MIX29;
		}
		else
		{
			/*FF_DL bigger than 4095*/
			/*update local information*/
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_FF_DATA_OFFSET_BT4095_MIX29;
		}
	}
	#endif
	else
	{}

    /*initialize SDU information*/
	CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen = CanTp_Channels[ChannelIdx].RxConnection.DataLen -
			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition - rxNSduCfgPtr->MetaDataLength;
    CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining = ffDl;
    CanTp_Channels[ChannelIdx].RxConnection.SduDataTotalCount = ffDl;

    /*initialize buffer information*/
    CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining = 0;

    /*initialize Flow control information*/
    CanTp_Channels[ChannelIdx].RxConnection.CurrentBs = 0;
    CanTp_Channels[ChannelIdx].RxConnection.CurrentCfSn = 0;
    CanTp_Channels[ChannelIdx].RxConnection.HandledCfCount = 0;
    CanTp_Channels[ChannelIdx].RxConnection.SentWftCount = 0;

    /*clear the event*/
    CanTp_Channels[ChannelIdx].RxConnection.EventFlags =
    		CanTp_Channels[ChannelIdx].RxConnection.EventFlags & ((uint8)~CANTP_CHANNEL_EVENT_FF_RECEIVED);
}

/*************************************************************************/
/*
 * Brief               Handle received SF.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx channel index
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, the channel is allowed to receive SF,
 *                     and SF received
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
FUNC(void, CANTP_CODE)
CanTp_RxHandleSFReception(uint8 ChannelIdx)
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxNSduCfgPtr;
    PduLengthType sfDl;
    uint8 chnIdx;

    rxNSduCfgPtr = CanTp_GetRxSduCfgByNSduId(CanTp_Channels[ChannelIdx].RxConnection.RcvdNSduId, &chnIdx);

    if ((CANTP_SF_RECEIVING == CanTp_Channels[ChannelIdx].RxConnection.RootState)
        || (CANTP_LARGE_RECEIVING == CanTp_Channels[ChannelIdx].RxConnection.RootState))
    {
        /*Another SF received when the channel is receiving a SDU*/
        /*Notify error for old SDU reception*/
        PduR_CanTpRxIndication(rxNSduCfgPtr->RxIPduId, E_NOT_OK);
    }

    sfDl = CanTp_RxGetSFDl(CanTp_Channels[ChannelIdx].RxConnection.LocalBuf, rxNSduCfgPtr);
    /*SF data length valid*/
    if (sfDl != 0x0u)
    {
        /*update channel runtime information*/
        CanTp_Channels[ChannelIdx].RxConnection.RootState = CANTP_SF_RECEIVING;
        CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_SF_START;
        CanTp_Channels[ChannelIdx].RxConnection.NSduId = CanTp_Channels[ChannelIdx].RxConnection.RcvdNSduId;
        CanTp_Channels[ChannelIdx].RxConnection.RcvdNSduId = 0;
        CanTp_Channels[ChannelIdx].RxConnection.HandleType = CANTP_FTYPE_SF;

        /*initialize SDU information*/
        if (CANTP_STANDARD == rxNSduCfgPtr->AddressingFormat)
        {
            /*standard SF*/
        	if (sfDl <= CANTP_SF_LEN_MAX_STD)
        	{
        		/*SF_DL less than or equal to 7*/
    			/*update local buffer information*/
    			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_STD;
        	}
    		#if (STD_ON == CANTP_FD)
        	else
        	{
        		/*SF_DL bigger than 7*/
    			/*update local buffer information*/
    			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_CANFD_STD;
        	}
    		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
        }
		#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
        else if (CANTP_EXTENDED == rxNSduCfgPtr->AddressingFormat)
        {
        	/*extended SF*/
        	if (sfDl <= CANTP_SF_LEN_MAX_EX)
        	{
        		/*SF_DL less than or equal to 7*/
    			/*update local buffer information*/
    			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_EX;
        	}
    		#if (STD_ON == CANTP_FD)
        	else
        	{
        		/*SF_DL bigger than 7*/
    			/*update local buffer information*/
    			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_CANFD_EX;
        	}
    		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
        }
    	#endif
		#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
        else if (CANTP_NORMALFIXED == rxNSduCfgPtr->AddressingFormat)
        {
    		if (sfDl <= CANTP_SF_LEN_MAX_NF)
    		{
    			/*SF_DL less than or equal to 7*/
    			/*update local buffer information*/
    			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_NF;
    		}
    		#if (STD_ON == CANTP_FD)
    		else
    		{
    			/*SF_DL bigger than 7*/
    			/*update local buffer information*/
    			CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_CANFD_NF;
    		}
    		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
        }
    	#endif
		#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
		else if (CANTP_MIXED == rxNSduCfgPtr->AddressingFormat)
		{
			if (sfDl <= CANTP_SF_LEN_MAX_MIX11)
			{
				/*SF_DL less than or equal to 7*/
				/*update local buffer information*/
				CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_MIX11;
			}
			#if (STD_ON == CANTP_FD)
			else
			{
				/*SF_DL bigger than 7*/
				/*update local buffer information*/
				CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_CANFD_MIX11;
			}
			#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
		}
		#endif
		#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
		else if (CANTP_MIXED29BIT == rxNSduCfgPtr->AddressingFormat)
		{
			if (sfDl <= CANTP_SF_LEN_MAX_MIX29)
			{
				/*SF_DL less than or equal to 7*/
				/*update local buffer information*/
				CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_MIX29;
			}
			#if (STD_ON == CANTP_FD)
			else
			{
				/*SF_DL bigger than 7*/
				/*update local buffer information*/
				CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = CANTP_SF_DATA_OFFSET_CANFD_MIX29;
			}
			#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
		}
		#endif
		else
		{}

        CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen = sfDl;
        CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining = sfDl;
        CanTp_Channels[ChannelIdx].RxConnection.SduDataTotalCount = sfDl;

        /*initialize buffer information*/
        CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining = 0;

        /*clear the event*/
        CanTp_Channels[ChannelIdx].RxConnection.EventFlags =
        		CanTp_Channels[ChannelIdx].RxConnection.EventFlags & ((uint8)~CANTP_CHANNEL_EVENT_SF_RECEIVED);
    }
}

FUNC(void, CANTP_CODE)
CanTp_RxHandleReceiveCancel(uint8 ChannelIdx)
{
    PduIdType sduId;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    uint8 chnIdx;

    sduId = CanTp_Channels[ChannelIdx].RxConnection.NSduId;
    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(sduId, &chnIdx);
    /*Release the resource related with the channel*/
	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
	{
		CanTp_InitChannel(ChannelIdx);
	}
	else
	{
		CanTp_InitRxChannel(ChannelIdx);
	}

    /*Notify the upper*/
    PduR_CanTpRxIndication(rxSduCfgPtr->RxIPduId, E_NOT_OK);
}
/*************************************************************************/
/*
 * Brief               Handle confirmation for FC.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx channel index
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, the channel is waiting for the confirmation
 *                     of FC frame, and a FC frame confirmed.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
FUNC(void, CANTP_CODE)
CanTp_RxHandleFCCfm(uint8 ChannelIdx)
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    uint8 chnIdx;
    uint32 N_Cr;

    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(CanTp_Channels[ChannelIdx].RxConnection.NSduId, &chnIdx);

    if (CANTP_RX_LARGE_V4FCWT_CFM == CanTp_Channels[ChannelIdx].RxConnection.Substate)
    {
        /*transit to RX_LARGE_START, which will try to get buffer again*/
        CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_START;
        CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NB;
        CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = rxSduCfgPtr->Nbr;
        CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
    }
    else if (CANTP_RX_LARGE_V4FCCTS_CFM == CanTp_Channels[ChannelIdx].RxConnection.Substate)
    {
        /*FC_CTS sent, start to waiting for CFs*/
        CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_V4CF;
        if (rxSduCfgPtr->Ncr != NULL_PTR)
        {
        	N_Cr = *(rxSduCfgPtr->Ncr);
            CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NC;
            CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = N_Cr;
            CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
        }
        else
        {
        	CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_TIMER_NONE;
        }
    }
    else
    {
        /*will not happen with handling of filtering when indicated by CanIf*/
    }

    /*clear the event*/
    CanTp_Channels[ChannelIdx].RxConnection.EventFlags =
    		CanTp_Channels[ChannelIdx].RxConnection.EventFlags & ((uint8)~CANTP_CHANNEL_EVENT_TXFC_CONFIRMED);
}

/*************************************************************************/
/*
 * Brief               Back ground handling for receiving SF,
 *                     in this state the channel is trying to get buffer to store
 *                     received SF.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx channel index
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, the channel is trying to get buffer to store
 *                     received SF.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
FUNC(void, CANTP_CODE)
CanTp_RxHandleSFStart(uint8 ChannelIdx)
{
    PduInfoType pduInfo;
    uint8 chnIdx;
    PduInfoType *pduInfoPtr = &pduInfo;
    BufReq_ReturnType bufRslt;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    PduLengthType bufferSize;
    PduIdType nSduId;
    PduIdType iPduId;
    PduLengthType pduLength;
    PduLengthType pduPosition;
    
    pduInfo.SduLength = 0;
    nSduId = CanTp_Channels[ChannelIdx].RxConnection.NSduId;
    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(nSduId, &chnIdx);
    iPduId = rxSduCfgPtr->RxIPduId;

	#if (STD_ON == CANTP_GENERIC_CONNECTION_SUPPORT)
    if (CanTp_Channels[ChannelIdx].RxConnection.MetaDataLength > 0u)
    {
    	CanTp_ConstructForwardRxMetaData(ChannelIdx, rxSduCfgPtr, pduInfoPtr);
    }
	#endif

    pduLength = CanTp_Channels[ChannelIdx].RxConnection.SduDataTotalCount;
    bufRslt = PduR_CanTpStartOfReception(iPduId, pduInfoPtr, pduLength, &bufferSize);

    /*handle according the result of request RX buffer*/
    switch (bufRslt)
    {
        case BUFREQ_OK:
        {
        	if (bufferSize >= pduLength)
        	{
        		pduPosition = CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition;
				pduInfo.SduDataPtr = &CanTp_Channels[ChannelIdx].RxConnection.LocalBuf[pduPosition];
				pduInfo.SduLength = CanTp_Channels[ChannelIdx].RxConnection.LocalDataLen;
        		bufRslt = PduR_CanTpCopyRxData(iPduId, pduInfoPtr, &bufferSize);
            	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
            	{
            		CanTp_InitChannel(ChannelIdx);
            	}
            	else
            	{
            		CanTp_InitRxChannel(ChannelIdx);
            	}
        		if (bufRslt == BUFREQ_OK)
        		{
        			PduR_CanTpRxIndication(iPduId, E_OK);
        		}
        		else
        		{
        			PduR_CanTpRxIndication(iPduId, E_NOT_OK);
        		}
        	}
        	else
        	{
        		/*SWS_CanTp_00339,a smaller available buffer size than needed for the already received data*/
        		/*abort the reception of the N-SDU*/
            	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
            	{
            		CanTp_InitChannel(ChannelIdx);
            	}
            	else
            	{
            		CanTp_InitRxChannel(ChannelIdx);
            	}
        		PduR_CanTpRxIndication(iPduId, E_NOT_OK);
        	}
            break;
        } /*ENDOF case BUFREQ_OK*/
        case BUFREQ_E_NOT_OK:
        {
        	/*Release the resource of the channel*/
        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
        	{
        		CanTp_InitChannel(ChannelIdx);
        	}
        	else
        	{
        		CanTp_InitRxChannel(ChannelIdx);
        	}
        	break;
        }
        case BUFREQ_E_OVFL:
        {
            /*Release the resource of the channel*/
        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
        	{
        		CanTp_InitChannel(ChannelIdx);
        	}
        	else
        	{
        		CanTp_InitRxChannel(ChannelIdx);
        	}

            /*Notify the upper for error*/
            PduR_CanTpRxIndication(iPduId, E_NOT_OK);
            break;
        }
        default:
        {
            /*invalid return value*/
            /*Release the resource of the channel*/
        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
        	{
        		CanTp_InitChannel(ChannelIdx);
        	}
        	else
        	{
        		CanTp_InitRxChannel(ChannelIdx);
        	}

            /*Notify the upper for error*/
            PduR_CanTpRxIndication(iPduId, E_NOT_OK);
            break;
        }
    } /*END OF switch (bufRslt)*/
}

/*************************************************************************/
/*
 * Brief               Back ground handling for large SDU receiving, trying to get RX buffer.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx channel index
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, the channel is trying to get buffer to store
 *                     received FF or CF.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
FUNC(void, CANTP_CODE)
 CanTp_RxHandleLargeStart(uint8 ChannelIdx)
{
    PduInfoType pduInfo;
    uint8 chnIdx;
    uint8 wtfMax;
    P2VAR(PduInfoType, AUTOMATIC, AUTOMATIC) pduInfoPtr = &pduInfo;
    Std_ReturnType rslt;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    PduIdType nSduId;
    PduIdType iPduId;
    uint32 N_Ar;

    nSduId = CanTp_Channels[ChannelIdx].RxConnection.NSduId;
    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(nSduId, &chnIdx);
    iPduId = rxSduCfgPtr->RxIPduId;

    if (CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer == CANTP_NB)
    {
        pduInfo.SduDataPtr = NULL_PTR;
        pduInfo.SduLength = 0;
        /*query the upper layer about the available buffer size*/
    	(void)PduR_CanTpCopyRxData(iPduId, pduInfoPtr, &CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining);
    }

    /*if or not have enough buffer size in the upper layer to store the next block*/
    rslt = CanTp_CompareBufferWithBs(ChannelIdx);
    if ( E_NOT_OK == rslt)
    {
    	/*upper buffer smaller than next block size, can not receive*/
		if ((CANTP_NB == CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer)
				&&(0u == CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime))
		{
			if (rxSduCfgPtr->RxWftMax != NULL_PTR)
			{
				wtfMax = *(rxSduCfgPtr->RxWftMax);
			}
			else
			{
				wtfMax = 0xFF;
			}

			/*Nbr expires*/
			if (0u != wtfMax)
			{
				/*If the whole SDU will be send in more than one single block(I.E. BS is not zero) and it the end of current block
				 * but not the last block, or if currently it is handling First Frame, it is allowed to send FC_WAIT*/
				if ((CANTP_FTYPE_FF == CanTp_Channels[ChannelIdx].RxConnection.HandleType)
					|| ((CanTp_Channels[ChannelIdx].RxConnection.CurrentBs == CanTp_Channels[ChannelIdx].RxConnection.HandledCfCount)
						&& (CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining > 0u)))
				{
					/*Try to send FC_WAIT*/
					if (wtfMax <= CanTp_Channels[ChannelIdx].RxConnection.SentWftCount)
					{
						/*Can not send any more FC_WAIT. Abort this reception*/
						/*release resource of this channel*/
			        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
			        	{
			        		CanTp_InitChannel(ChannelIdx);
			        	}
			        	else
			        	{
			        		CanTp_InitRxChannel(ChannelIdx);
			        	}
						PduR_CanTpRxIndication(iPduId, E_NOT_OK);
					}
					else
					{
						/*Send FC_WAIT and then wait for the confirmation*/
						pduInfo.SduLength = CanTp_ConstructFCPci(ChannelIdx, CANTP_FC_FS_WT, 0, 0);
						pduInfo.SduDataPtr = CanTp_Channels[ChannelIdx].RxConnection.FcBuf;

						rslt = CanIf_Transmit(rxSduCfgPtr->TxFcLPduId, pduInfoPtr);
						if (E_OK == rslt)
						{
							/*send FC OK*/
							CanTp_Channels[ChannelIdx].RxConnection.SentWftCount++;
							/*transit to waiting for confirmation of FC_WAIT*/
							CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_V4FCWT_CFM;
						    if (rxSduCfgPtr->Nar != NULL_PTR)
						    {
						    	N_Ar = *(rxSduCfgPtr->Nar);
								CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NA;
								CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = N_Ar;
								CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
						    }
						    else
						    {
						    	CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_TIMER_NONE;
						    }
						}
						else
						{
				        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
				        	{
				        		CanTp_InitChannel(ChannelIdx);
				        	}
				        	else
				        	{
				        		CanTp_InitRxChannel(ChannelIdx);
				        	}
							PduR_CanTpRxIndication(iPduId, E_NOT_OK);
						}
					}
				} /*END OF try to send FC_WAIT*/
			}
		}/*End of Nbr expires*/
    }
    else
    {
    	/*upper buffer bigger than next block size*/
		/*FF reception finished or current BS reception finished, send FC_CTS to start a block*/
    	rslt = CanTp_RxBlockStart(ChannelIdx);
    	if (E_NOT_OK == rslt)
    	{
        	if (CanTp_Channels[ChannelIdx].ChannelMode == CANTP_MODE_HALF_DUPLEX)
        	{
        		CanTp_InitChannel(ChannelIdx);
        	}
        	else
        	{
        		CanTp_InitRxChannel(ChannelIdx);
        	}
			PduR_CanTpRxIndication(iPduId, E_NOT_OK);
    	}
    }
}

/*************************************************************************/
/*
 * Brief               Get SDU configuration by N-SDU ID.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      CanTpRxSduId ID of the SDU
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              pointer to the configuration structure of this SDU
 *                     NULL_PTR if the no SDU matched
 * PreCondition        Module initialized
 * CallByAPI           CanTp Internal
 */
/*************************************************************************/
FUNC(P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST), CANTP_CODE)
CanTp_GetRxSduCfgByNSduId(PduIdType CanTpRxSduId, uint8* channelId)
{
	uint8 chnIdx;
    uint8 rxNSduIdx;
    P2CONST(CanTp_ChannelType, AUTOMATIC, CANTP_VAR) channelPtr;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) result = NULL_PTR;

    for (chnIdx = 0; (NULL_PTR == result) && (chnIdx < CANTP_CHANNEL_NUMBER); chnIdx++)
    {
    	channelPtr = &CanTp_CfgData.CanTpChannel[chnIdx];
		for (rxNSduIdx = 0; (NULL_PTR == result) && (rxNSduIdx < channelPtr->RxNSduNum); rxNSduIdx++)
		{
			if (channelPtr->RxNSdus[rxNSduIdx].RxNSduId == CanTpRxSduId)
			{
				result = &channelPtr->RxNSdus[rxNSduIdx];
				*channelId = chnIdx;
			}
		}
    }
    return result;
}
/*************************************************************************/
/*
 * Brief               Get FF_DL information from the data content of FF.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      CanTpRxPduPtr pointer to data
 *                     RxNSduCfgPtr pointer to configuration structure
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              FF_DL
 * PreCondition        Module initialized, the channel received a FF.
 * CallByAPI           CanTp_RxIndication and background handling
 */
/*************************************************************************/
FUNC(PduLengthType, CANTP_CODE)
CanTp_RxGetFFDl(
    P2CONST(uint8, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr,
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr)
{
    /*because PduLengthType is uint16, so FFDL can not bigger than 65535*/
	PduLengthType ffDl = 0;

    /*check FF DL*/
    if (CANTP_STANDARD == RxNSduCfgPtr->AddressingFormat)
    {
        /*PCI starts at byte[0]*/
        ffDl = (PduLengthType)((PduLengthType)CanTpRxPduPtr[CANTP_PCI_OFFSET_STD] & (PduLengthType)CANTP_FF_DL_MASK);
        ffDl <<= CANTP_OFFSET_BYTE_PART;
        ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_STD + 1u];
        /*FFDL > 4095*/
        if (0x0u == ffDl)
        {
        	ffDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_STD + 2u];
        	ffDl <<= CANTP_OFFSET_BYTE_PART;
        	ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_STD + 3u];
        	ffDl <<= CANTP_OFFSET_BYTE_PART;
        	ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_STD + 4u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_STD + 5u];
        }
    }
	#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_EXTENDED == RxNSduCfgPtr->AddressingFormat)
    {
        /*PCI starts at byte[1]*/
        ffDl = (PduLengthType)((PduLengthType)CanTpRxPduPtr[CANTP_PCI_OFFSET_EX] & (PduLengthType)CANTP_FF_DL_MASK);
        ffDl <<= CANTP_OFFSET_BYTE_PART;
        ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_EX + 1u];
		/*FFDL > 4095*/
		if (0x0u == ffDl)
		{
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_EX + 2u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_EX + 3u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_EX + 4u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_EX + 5u];
		}
    }
	#endif
	#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_NORMALFIXED == RxNSduCfgPtr->AddressingFormat)
    {
        /*PCI starts at byte[0]*/
        ffDl = (PduLengthType)((PduLengthType)CanTpRxPduPtr[CANTP_PCI_OFFSET_NF] & (PduLengthType)CANTP_FF_DL_MASK);
        ffDl <<= CANTP_OFFSET_BYTE_PART;
        ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_NF + 1u];
		/*FFDL > 4095*/
		if (0x0u == ffDl)
		{
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_NF + 2u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_NF + 3u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_NF + 4u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_NF + 5u];
		}
    }
	#endif
	#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_MIXED == RxNSduCfgPtr->AddressingFormat)
    {
        /*PCI starts at byte[1]*/
        ffDl = (PduLengthType)((PduLengthType)CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11] & (PduLengthType)CANTP_FF_DL_MASK);
        ffDl <<= CANTP_OFFSET_BYTE_PART;
        ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11 + 1u];
		/*FFDL > 4095*/
		if (0x0u == ffDl)
		{
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11 + 2u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11 + 3u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11 + 4u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11 + 5u];
		}
    }
	#endif
	#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_MIXED29BIT == RxNSduCfgPtr->AddressingFormat)
    {
        /*PCI starts at byte[1]*/
        ffDl = (PduLengthType)((PduLengthType)CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29] & (PduLengthType)CANTP_FF_DL_MASK);
        ffDl <<= CANTP_OFFSET_BYTE_PART;
        ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29 + 1u];
		/*FFDL > 4095*/
		if (0x0u == ffDl)
		{
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29 + 2u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29 + 3u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29 + 4u];
			ffDl <<= CANTP_OFFSET_BYTE_PART;
			ffDl = ffDl + CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29 + 5u];
		}
    }
	#endif
    else
    {}

    return ffDl;
}

/*************************************************************************/
/*
 * Brief               Get SFF_DL information from the data content of SF.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      CanTpRxPduPtr pointer to data
 *                     RxNSduCfgPtr pointer to configuration structure
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              FF_DL
 * PreCondition        Module initialized, the channel received a SF.
 * CallByAPI           CanTp_RxIndication and background handling
 */
/*************************************************************************/
FUNC(PduLengthType, CANTP_CODE)
CanTp_RxGetSFDl(
    P2CONST(uint8, AUTOMATIC, CANTP_APPL_CONST) CanTpRxPduPtr,
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr)
{
    uint8 sfDl = 0;

    /*check SF DL*/
    if (CANTP_STANDARD == RxNSduCfgPtr->AddressingFormat)
    {
        /*PCI is byte[0]*/
        sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_STD] & CANTP_SF_DL_MASK;
		#if (STD_ON == CANTP_FD)
        if (0x0u == sfDl)
        {
        	/*CanFD only*/
        	if (CAN_FD == RxNSduCfgPtr->CanFrameType)
        	{
        		sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_STD + 1u];
        	}
        }
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
    }
	#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_EXTENDED == RxNSduCfgPtr->AddressingFormat)
    {
        /*PCI is byte[1]*/
        sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_EX] & CANTP_SF_DL_MASK;
		#if (STD_ON == CANTP_FD)
        if (0x0u == sfDl)
        {
        	/*CanFD only*/
        	if (CAN_FD == RxNSduCfgPtr->CanFrameType)
        	{
        		sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_EX + 1u];
        	}
        }
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
    }
	#endif
	#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_NORMALFIXED == RxNSduCfgPtr->AddressingFormat)
	{
		/*PCI is byte[0]*/
		sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_NF] & CANTP_SF_DL_MASK;
		#if (STD_ON == CANTP_FD)
		if (0x0u == sfDl)
		{
			/*CanFD only*/
			if (CAN_FD == RxNSduCfgPtr->CanFrameType)
			{
				sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_NF + 1u];
			}
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#endif
	#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED == RxNSduCfgPtr->AddressingFormat)
	{
		/*PCI is byte[1]*/
		sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11] & CANTP_SF_DL_MASK;
		#if (STD_ON == CANTP_FD)
		if (0x0u == sfDl)
		{
			/*CanFD only*/
			if (CAN_FD == RxNSduCfgPtr->CanFrameType)
			{
				sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX11 + 1u];
			}
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#endif
	#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED29BIT == RxNSduCfgPtr->AddressingFormat)
	{
		/*PCI is byte[1]*/
		sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29] & CANTP_SF_DL_MASK;
		#if (STD_ON == CANTP_FD)
		if (0x0u == sfDl)
		{
			/*CanFD only*/
			if (CAN_FD == RxNSduCfgPtr->CanFrameType)
			{
				sfDl = CanTpRxPduPtr[CANTP_PCI_OFFSET_MIX29 + 1u];
			}
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#endif
	else
	{}

    return sfDl;
}

#if (CANTP_GENERIC_CONNECTION_SUPPORT == STD_ON)
FUNC(Std_ReturnType, CANTP_CODE)CanTp_SaveRxMetaDataInfo(
	uint8 channelId,
	P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
	P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxInfoPtr
	)
{
	P2VAR(CanTp_ConnectionChannelType, AUTOMATIC, CANTP_VAR_POWER_ON_INIT) channelPtr = NULL_PTR;
	PduLengthType metaDataPos;
	Std_ReturnType ret = E_OK;

	channelPtr = &CanTp_Channels[channelId];
	metaDataPos = CanTpRxInfoPtr->SduLength - RxNSduCfgPtr->MetaDataLength;

	switch (RxNSduCfgPtr->AddressingFormat)
	{
		/*other addressing mode by OEM dependent */
		#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_EXTENDED:
		{
			break;
		}
		#endif
		#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_MIXED:
		{
			break;
		}
		#endif
		#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
		case  CANTP_NORMALFIXED:
		{
			channelPtr->RxConnection.MetaDataN_SA = CanTpRxInfoPtr->SduDataPtr[metaDataPos + CANTP_SA_OFFSET_META_NF];
			channelPtr->RxConnection.MetaDataN_TA = CanTpRxInfoPtr->SduDataPtr[metaDataPos + CANTP_TA_OFFSET_META_NF];
			if (RxNSduCfgPtr->NSa != NULL_PTR)
			{
				if (channelPtr->RxConnection.MetaDataN_SA != *(RxNSduCfgPtr->NSa))
				{
					ret = E_NOT_OK;
				}
			}
			if (RxNSduCfgPtr->NTa != NULL_PTR)
			{
				if (channelPtr->RxConnection.MetaDataN_TA != *(RxNSduCfgPtr->NTa))
				{
					ret = E_NOT_OK;
				}
			}
			break;
		}
		#endif
		#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
		case  CANTP_MIXED29BIT:
		{
			/*at the end of sdu*/
			channelPtr->RxConnection.MetaDataN_SA = CanTpRxInfoPtr->SduDataPtr[metaDataPos + CANTP_SA_OFFSET_META_MIX29];
			channelPtr->RxConnection.MetaDataN_TA = CanTpRxInfoPtr->SduDataPtr[metaDataPos + CANTP_TA_OFFSET_META_MIX29];
			if (RxNSduCfgPtr->NSa != NULL_PTR)
			{
				if (channelPtr->RxConnection.MetaDataN_SA != *(RxNSduCfgPtr->NSa))
				{
					ret = E_NOT_OK;
				}
			}
			if (RxNSduCfgPtr->NTa != NULL_PTR)
			{
				if (channelPtr->RxConnection.MetaDataN_TA != *(RxNSduCfgPtr->NTa))
				{
					ret = E_NOT_OK;
				}
			}
			break;
		}
		#endif
		default:
			break;
	}
	return ret;
}

static FUNC(void, CANTP_CODE)CanTp_ConstructForwardRxMetaData(
	uint8 channelId,
	P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
	P2VAR(PduInfoType, AUTOMATIC, CANTP_VAR) CanTpRxInfoPtr
	)
{
	P2VAR(CanTp_ConnectionChannelType, AUTOMATIC, CANTP_VAR_POWER_ON_INIT) channelPtr = NULL_PTR;

	channelPtr = &CanTp_Channels[channelId];
	CanTpRxInfoPtr->SduLength = channelPtr->RxConnection.MetaDataLength;

	switch (RxNSduCfgPtr->AddressingFormat)
	{
		#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_EXTENDED:
			if (RxNSduCfgPtr->NTa != NULL_PTR)
			{
				CanTpRxInfoPtr->SduDataPtr[CANTP_TA_OFFSET_META_EX] = *(RxNSduCfgPtr->NTa);
			}
			break;
		#endif
		#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_NORMALFIXED:
			CanTpRxInfoPtr->SduDataPtr[CANTP_SA_OFFSET_META_NF] = channelPtr->RxConnection.MetaDataN_SA;
			CanTpRxInfoPtr->SduDataPtr[CANTP_TA_OFFSET_META_NF] = channelPtr->RxConnection.MetaDataN_TA;
			break;
		#endif
		#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_MIXED:
			if (RxNSduCfgPtr->NAe != NULL_PTR)
			{
				CanTpRxInfoPtr->SduDataPtr[CANTP_AE_OFFSET_META_MIX] = *(RxNSduCfgPtr->NAe);
			}
			break;
		#endif
		#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_MIXED29BIT:
			CanTpRxInfoPtr->SduDataPtr[CANTP_SA_OFFSET_META_MIX29] = channelPtr->RxConnection.MetaDataN_SA;
			CanTpRxInfoPtr->SduDataPtr[CANTP_TA_OFFSET_META_MIX29] = channelPtr->RxConnection.MetaDataN_TA;
			if (RxNSduCfgPtr->NAe != NULL_PTR)
			{
				CanTpRxInfoPtr->SduDataPtr[CANTP_AE_OFFSET_META_MIX29] = *(RxNSduCfgPtr->NAe);
			}
			break;
		#endif
		default:
			break;
	}
}

static FUNC(PduLengthType, CANTP_CODE)
CanTp_ConstructFCMetaData(
	uint8 channelId,
	P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr
	)
{
    PduLengthType position;

	position = CanTp_Channels[channelId].RxConnection.LocalDataPosition;

	switch (RxNSduCfgPtr->AddressingFormat)
	{
		#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_EXTENDED:
		{
			break;
		}
		#endif
		#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_MIXED:
		{
			break;
		}
		#endif
		#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_NORMALFIXED:
		{
			CanTp_Channels[channelId].RxConnection.FcBuf[position] =
					CanTp_Channels[channelId].TxConnection.MetaDataN_TA;

			CanTp_Channels[channelId].RxConnection.FcBuf[position + 1u] =
					CanTp_Channels[channelId].TxConnection.MetaDataN_SA;
			break;
		}
		#endif
		#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
		case CANTP_MIXED29BIT:
		{
			CanTp_Channels[channelId].RxConnection.FcBuf[position] =
					CanTp_Channels[channelId].TxConnection.MetaDataN_TA;

			CanTp_Channels[channelId].RxConnection.FcBuf[position + 1u] =
					CanTp_Channels[channelId].TxConnection.MetaDataN_SA;
			break;
		}
		#endif
		default:
			break;
	}

	return position + 1u;
}

FUNC(Std_ReturnType, CANTP_CODE)
CanTp_CheckRxCFMetaData(
	uint8 channelIdx,
	P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) RxNSduCfgPtr,
	P2CONST(PduInfoType, AUTOMATIC, CANTP_APPL_CONST) CanTpRxInfoPtr
	)
{
	   P2VAR(CanTp_ConnectionChannelType, AUTOMATIC, CANTP_VAR_POWER_ON_INIT) channelPtr = NULL_PTR;
	   Std_ReturnType result = E_OK;

	   channelPtr = &CanTp_Channels[channelIdx];
	   switch (RxNSduCfgPtr->AddressingFormat)
	   	{
	   		#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
	   		case CANTP_EXTENDED:
	   		{
	   			break;
	   		}
	   		#endif
	   		#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
	   		case CANTP_MIXED:
	   		{
	   			break;
	   		}
	   		#endif
	   		#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
	   		case CANTP_NORMALFIXED:
	   		{
	   		    if ((channelPtr->RxConnection.MetaDataN_SA != CanTpRxInfoPtr->SduDataPtr[CanTpRxInfoPtr->SduLength - 1u])||
	   				(channelPtr->RxConnection.MetaDataN_TA != CanTpRxInfoPtr->SduDataPtr[CanTpRxInfoPtr->SduLength]))
	   		    {
	   			    result = E_NOT_OK;
	   		    }
	   			break;
	   		}
	   		#endif
	   		#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
	   		case CANTP_MIXED29BIT:
	   		{
	   			if ((channelPtr->RxConnection.MetaDataN_SA != CanTpRxInfoPtr->SduDataPtr[CanTpRxInfoPtr->SduLength - 1u])||
					(channelPtr->RxConnection.MetaDataN_TA != CanTpRxInfoPtr->SduDataPtr[CanTpRxInfoPtr->SduLength]))
				{
					result = E_NOT_OK;
				}
	   			break;
	   		}
	   		#endif
	   		default:
	   			break;
	   	}
	   return result;
}
#endif
/*************************************************************************/
/*
 * Brief               Construct Flow Control frame according to the parameter.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 *                     FsValue FC FS value
 *                     BSValue BS value for FC
 *                     STminValue STMin for FC
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              the length of constructed FC
 * PreCondition        Module initialized, a FC transmitting needed.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
static FUNC(PduLengthType, CANTP_CODE)
CanTp_ConstructFCPci(
    uint8 ChannelIdx,
    uint8 FsValue,
    uint8 BSValue,
    uint8 STminValue)
{
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    PduLengthType fcFrameLen = 0u;
    uint8 chnIdx;

    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(CanTp_Channels[ChannelIdx].RxConnection.NSduId, &chnIdx);

    if (CANTP_STANDARD == rxSduCfgPtr->AddressingFormat)
    {
        /*STANDARD SDU*/
        CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_PCI_OFFSET_STD] = CANTP_FTYPE_FC | FsValue;
        CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_BS_STD] = BSValue;
        CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_STMIN_STD] = STminValue;
        fcFrameLen = CANTP_FC_LEN_STD;
    }
	#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
    else if (CANTP_EXTENDED == rxSduCfgPtr->AddressingFormat)
    {
        /*EXTENDED SDU*/
        /*first byte OEM dependent*/
        CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_PCI_OFFSET_EX] = CANTP_FTYPE_FC | FsValue;
        CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_BS_EX] = BSValue;
        CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_STMIN_EX] = STminValue;
        fcFrameLen = CANTP_FC_LEN_EX;
    }
	#endif
	#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_NORMALFIXED == rxSduCfgPtr->AddressingFormat)
	{
		/*normal fixed SDU*/
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_PCI_OFFSET_NF] = CANTP_FTYPE_FC | FsValue;
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_BS_NF] = BSValue;
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_STMIN_NF] = STminValue;
		fcFrameLen = CANTP_FC_LEN_NF;
	}
	#endif
	#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED == rxSduCfgPtr->AddressingFormat)
	{
		/*mix11 SDU*/
		/*first byte OEM dependent*/
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_PCI_OFFSET_MIX11] = CANTP_FTYPE_FC | FsValue;
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_BS_MIX11] = BSValue;
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_STMIN_MIX11] = STminValue;
		fcFrameLen = CANTP_FC_LEN_MIX11;
	}
	#endif
	#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED29BIT == rxSduCfgPtr->AddressingFormat)
	{
		/*mix29 SDU*/
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_PCI_OFFSET_MIX29] = CANTP_FTYPE_FC | FsValue;
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_BS_MIX29] = BSValue;
		CanTp_Channels[ChannelIdx].RxConnection.FcBuf[CANTP_FC_OFFSET_STMIN_MIX29] = STminValue;
		fcFrameLen = CANTP_FC_LEN_MIX29;
	}
	#endif
	else
	{}

    CanTp_Channels[ChannelIdx].RxConnection.LocalDataPosition = fcFrameLen;

    /*SWS_CanTp_00347*/
    if (CANTP_PADDING_ON == rxSduCfgPtr->RxPaddingActivation)
    {
		CanTp_MemorySet(
			&CanTp_Channels[ChannelIdx].RxConnection.FcBuf[fcFrameLen],
			CANTP_PADDING_BYTE,
			CANTP_CAN20_FRAME_LEN_MAX - fcFrameLen);
		fcFrameLen = CANTP_CAN20_FRAME_LEN_MAX;
    }
    else
    {
    	/*no padding*/
    }

	#if (CANTP_GENERIC_CONNECTION_SUPPORT == STD_ON)
	if (CanTp_Channels[ChannelIdx].RxConnection.MetaDataLength > 0u)
	{
		fcFrameLen = CanTp_ConstructFCMetaData(ChannelIdx, rxSduCfgPtr);
	}
	#endif

    /*return the FC frame length contain meta data length if it have meta data*/
    return fcFrameLen;
}
static FUNC(Std_ReturnType, CANTP_CODE)
CanTp_CompareBufferWithBs(uint8 ChannelIdx)
{
    PduLengthType blockDataLen = 0xFFFFu;
    uint8 chnIdx;
    Std_ReturnType rslt;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;

    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(CanTp_Channels[ChannelIdx].RxConnection.NSduId, &chnIdx);

	if (CANTP_STANDARD == rxSduCfgPtr->AddressingFormat)
	{
		/*Standard SDU*/
		/*CF composed of this block,CAN2.0 and CANFD is the same format, just different with length*/
		if (CAN20 == rxSduCfgPtr->CanFrameType)
		{
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_STD;
		}
		#if (STD_ON == CANTP_FD)
		else
		{
			/*CAN_FD*/
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_CANFD_STD;
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_EXTENDED == rxSduCfgPtr->AddressingFormat)
	{
		/*extended SDU*/
		/*CF composed of this block, CAN2.0 and CANFD is the same format, just different with length*/
		if (CAN20 == rxSduCfgPtr->CanFrameType)
		{
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_EX;
		}
		#if (STD_ON == CANTP_FD)
		else
		{
			/*CAN_FD*/
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_CANFD_EX;
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#endif
	#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_NORMALFIXED == rxSduCfgPtr->AddressingFormat)
	{
		/*normal fixed SDU*/
		/*CF composed of this block, CAN2.0 and CANFD is the same format, just different with length*/
		if (CAN20 == rxSduCfgPtr->CanFrameType)
		{
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_NF;
		}
		#if (STD_ON == CANTP_FD)
		else
		{
			/*CAN_FD*/
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_CANFD_NF;
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#endif
	#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED == rxSduCfgPtr->AddressingFormat)
	{
		/*mix11 SDU*/
		/*CF composed of this block, CAN2.0 and CANFD is the same format, just different with length*/
		if (CAN20 == rxSduCfgPtr->CanFrameType)
		{
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_MIX11;
		}
		#if (STD_ON == CANTP_FD)
		else
		{
			/*CAN_FD*/
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_CANFD_MIX11;
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#endif
	#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
	else if (CANTP_MIXED29BIT == rxSduCfgPtr->AddressingFormat)
	{
		/*mix29 SDU*/
		/*CF composed of this block, CAN2.0 and CANFD is the same format, just different with length*/
		if (CAN20 == rxSduCfgPtr->CanFrameType)
		{
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_MIX29;
		}
		#if (STD_ON == CANTP_FD)
		else
		{
			/*CAN_FD*/
			blockDataLen =
					(PduLengthType)CanTp_Channels[ChannelIdx].RxConnection.CurrentBs * CANTP_CF_DATALEN_CANFD_MIX29;
		}
		#endif/*ENDOF #if (STD_ON == CANTP_FD)*/
	}
	#endif
	else
	{}

	if (CanTp_Channels[ChannelIdx].RxConnection.UpperBufRemaining > blockDataLen)
	{
		rslt = E_OK;
	}
	else
	{
		rslt = E_NOT_OK;
	}
	return rslt;
}
/*************************************************************************/
/*
 * Brief               Calculate the BS value according to the buffer length and remain data length.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, a FC transmitting needed to start a new block.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
static FUNC(void, CANTP_CODE)
CanTp_CalcBS(uint8 ChannelIdx)
{
    PduLengthType blockDataLen;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    uint8 bs;
    uint8 chnIdx;

    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(CanTp_Channels[ChannelIdx].RxConnection.NSduId, &chnIdx);
    /*check changParameter of BS is done or not*/
    if ((CanTp_Channels[ChannelIdx].RxConnection.EventFlags & CANTP_CHANNEL_EVENT_RXBSCHANGED) != 0u)
    {
    	bs = CanTp_Channels[ChannelIdx].RxConnection.ChangedBs;
    }
    else
    {
    	/*bs is not changed by api*/
    	if (rxSduCfgPtr->Bs != NULL_PTR)
    	{
    		bs = *(rxSduCfgPtr->Bs);
    	}
    	else
    	{
    		bs = 0xFF;
    	}
    }

    if(0u == bs)
    {
        /*BS is 0, no more FC need from now on*/
        CanTp_Channels[ChannelIdx].RxConnection.CurrentBs = 0;
    }
    else
    {
        /*get the data length of this block using the minimum value between PDUR buffer length and
         * SDU remain data length. If the minimum value is zero, I.E. the PDUR remain buffer is 0, use 1
         * as the BS*/
        blockDataLen = CanTp_Channels[ChannelIdx].RxConnection.SduDataRemaining;

        if (0u == blockDataLen)
        {
            /*no more upper buffer space left */
            CanTp_Channels[ChannelIdx].RxConnection.CurrentBs = 1U;
        }
        else
        {
            if (CANTP_STANDARD == rxSduCfgPtr->AddressingFormat)
            {
            	/*Standard SDU*/
            	/*calculate CF block,CAN2.0 and CANFD is the same format, just different with length*/
            	if (CAN20 == rxSduCfgPtr->CanFrameType)
            	{
            		CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
            				(uint8)((blockDataLen + CANTP_CF_DATALEN_STD - 1u) / CANTP_CF_DATALEN_STD);
            	}
				#if (STD_ON == CANTP_FD)
            	else
            	{
            		/*CAN_FD*/
            		CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
            				(uint8)((blockDataLen + CANTP_CF_DATALEN_CANFD_STD - 1u) / CANTP_CF_DATALEN_CANFD_STD);
            	}
				#endif /*ENDOF #if (STD_ON == CANTP_FD)*/
            }
			#if (CANTP_EXTENDED_ADDRESSING_SUPPORT == STD_ON)
            else if (CANTP_EXTENDED == rxSduCfgPtr->AddressingFormat)
            {
            	/*extended SDU*/
            	/*calculate CF block,CAN2.0 and CANFD is the same format, just different with length*/
            	if (CAN20 == rxSduCfgPtr->CanFrameType)
            	{
            		CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
            				(uint8)((blockDataLen + CANTP_CF_DATALEN_EX - 1u) / CANTP_CF_DATALEN_EX);
            	}
				#if (STD_ON == CANTP_FD)
            	else
            	{
            		/*CAN_FD*/
            		CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
            				(uint8)((blockDataLen + CANTP_CF_DATALEN_CANFD_EX - 1u) / CANTP_CF_DATALEN_CANFD_EX);
            	}
				#endif /*ENDOF #if (STD_ON == CANTP_FD)*/
            }
			#endif
			#if (CANTP_NORMAL_FIXED_ADDRESSING_SUPPORT == STD_ON)
			else if (CANTP_NORMALFIXED == rxSduCfgPtr->AddressingFormat)
			{
				/*extended SDU*/
				/*calculate CF block,CAN2.0 and CANFD is the same format, just different with length*/
				if (CAN20 == rxSduCfgPtr->CanFrameType)
				{
					CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
							(uint8)((blockDataLen + CANTP_CF_DATALEN_NF - 1u) / CANTP_CF_DATALEN_NF);
				}
				#if (STD_ON == CANTP_FD)
				else
				{
					/*CAN_FD*/
					CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
							(uint8)((blockDataLen + CANTP_CF_DATALEN_CANFD_NF - 1u) / CANTP_CF_DATALEN_CANFD_NF);
				}
				#endif /*ENDOF #if (STD_ON == CANTP_FD)*/
			}
			#endif
			#if (CANTP_MIXED_ADDRESSING_SUPPORT == STD_ON)
			else if (CANTP_MIXED == rxSduCfgPtr->AddressingFormat)
			{
				/*extended SDU*/
				/*calculate CF block,CAN2.0 and CANFD is the same format, just different with length*/
				if (CAN20 == rxSduCfgPtr->CanFrameType)
				{
					CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
							(uint8)((blockDataLen + CANTP_CF_DATALEN_MIX11 - 1u) / CANTP_CF_DATALEN_MIX11);
				}
				#if (STD_ON == CANTP_FD)
				else
				{
					/*CAN_FD*/
					CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
							(uint8)((blockDataLen + CANTP_CF_DATALEN_CANFD_MIX11 - 1u) / CANTP_CF_DATALEN_CANFD_MIX11);
				}
				#endif /*ENDOF #if (STD_ON == CANTP_FD)*/
			}
			#endif
			#if (CANTP_MIXED29_ADDRESSING_SUPPORT == STD_ON)
			else if (CANTP_MIXED29BIT == rxSduCfgPtr->AddressingFormat)
			{
				/*extended SDU*/
				/*calculate CF block,CAN2.0 and CANFD is the same format, just different with length*/
				if (CAN20 == rxSduCfgPtr->CanFrameType)
				{
					CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
							(uint8)((blockDataLen + CANTP_CF_DATALEN_MIX29 - 1u) / CANTP_CF_DATALEN_MIX29);
				}
				#if (STD_ON == CANTP_FD)
				else
				{
					/*CAN_FD*/
					CanTp_Channels[ChannelIdx].RxConnection.CurrentBs =
							(uint8)((blockDataLen + CANTP_CF_DATALEN_CANFD_MIX29 - 1u) / CANTP_CF_DATALEN_CANFD_MIX29);
				}
				#endif /*ENDOF #if (STD_ON == CANTP_FD)*/
			}
			#endif
			else
			{}

            /*use the minimum value between calculated and the configured maximum value*/
            if (CanTp_Channels[ChannelIdx].RxConnection.CurrentBs > bs)
            {
                CanTp_Channels[ChannelIdx].RxConnection.CurrentBs = bs;
            }
        }
    } /*END OF BS needed*/
}

FUNC(boolean, CANTP_CODE)
CanTP_CheckRxChangeParameter(
		TPParameterType canTpParam,
		uint16 value)
{
	boolean paramValid = FALSE;

	if (((TP_BS == canTpParam)
			&&((value < 256u)||(value >= 0u)))
		||((TP_STMIN == canTpParam)
			&&((value > 0x0u)||(value < 0xFFu))))
	{
		paramValid = TRUE;
	}

	return paramValid;
}

/*************************************************************************/
/*
 * Brief               Start a block by sending FC_CTS if needed.
 * ServiceId           N/A
 * Sync/Async          Synchronous
 * Reentrancy          Non Reentrant
 * Param-Name[in]      ChannelIdx index of channel
 * Param-Name[out]     N/A
 * Param-Name[in/out]  N/A
 * Return              N/A
 * PreCondition        Module initialized, need to start a new block.
 * CallByAPI           CanTp_MainFunction
 */
/*************************************************************************/
static FUNC(Std_ReturnType , CANTP_CODE)
CanTp_RxBlockStart(uint8 ChannelIdx)
{
    PduInfoType pduInfo;
    P2CONST(CanTp_RxNSduType, AUTOMATIC, CANTP_CONST) rxSduCfgPtr;
    Std_ReturnType  rslt;
    uint8 stMin;
    uint8 chnIdx;
    uint32 N_Ar;

    rxSduCfgPtr = CanTp_GetRxSduCfgByNSduId(CanTp_Channels[ChannelIdx].RxConnection.NSduId, &chnIdx);

    /*check changParameter of STmin is done or not*/
	if ((CanTp_Channels[ChannelIdx].RxConnection.EventFlags & CANTP_CHANNEL_EVENT_RXSTMINCHANGED) != 0u)
	{
		stMin = CanTp_Channels[ChannelIdx].RxConnection.ChangedSTmin;
	}
	else
	{
		/*stmin is not changed by api*/
		if (rxSduCfgPtr->STmin != NULL_PTR)
		{
			stMin = *(rxSduCfgPtr->STmin);
		}
		else
		{
			stMin = 0;
		}
	}

    /*send FC_CTS*/
    pduInfo.SduLength = CanTp_ConstructFCPci(
											ChannelIdx,
											CANTP_FC_FS_CTS,
											CanTp_Channels[ChannelIdx].RxConnection.CurrentBs,
											stMin);
    pduInfo.SduDataPtr = CanTp_Channels[ChannelIdx].RxConnection.FcBuf;
      
    CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_V4FCCTS_CFM;  /*chenms 2013-9-26 19:32*/
    rslt = CanIf_Transmit(rxSduCfgPtr->TxFcLPduId,  &pduInfo);
    /*transit to waiting for confirmation of FC_CTS*/
    CanTp_Channels[ChannelIdx].RxConnection.Substate = CANTP_RX_LARGE_V4FCCTS_CFM;
    if (rxSduCfgPtr->Nar != NULL_PTR)
    {
    	N_Ar = *(rxSduCfgPtr->Nar);
        CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_NA;
        CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.RemainTime = N_Ar;
        CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.StartTime = Frt_ReadOutMS();
    }
    else
    {
    	CanTp_Channels[ChannelIdx].RxConnection.ChannelTimer.EnabledTimer = CANTP_TIMER_NONE;
    }

    CanTp_Channels[ChannelIdx].RxConnection.SentWftCount = 0;
    CanTp_Channels[ChannelIdx].RxConnection.HandledCfCount = 0;

    return rslt;
}
#define CANTP_STOP_SEC_CODE
#include "Cantp_MemMap.h"
/*=======[E N D   O F   F I L E]==============================================*/
